import _ from 'lodash'
import React, { Component, FormEvent, ReactNode } from 'react'
import { Form, Spin, Button } from 'antd'
import { IUdFormItem } from '../../../types'
import { WrappedFormUtils, FormComponentProps } from 'antd/lib/form/Form'
import { formUtils } from '../../../utils/formUtils'
import { ColProps } from 'antd/lib/col'
import classNames from 'classnames'
import { Value } from 'classnames'

class UdFormInner extends Component<IUdFormProps, IUdFormState> {
  static defaultProps = {
    labelCol: {
      xs: 24,
      sm: 24,
      md: 5,
      lg: 5,
      xl: 3,
      xxl: 3,
    },
    wrapperCol: {
      xs: 24,
      sm: 24,
      md: 18,
      lg: 15,
      xl: 12,
      xxl: 12,
    },
    tailFormItemLayout: {
      xs: {
        span: 24,
        offset: 0,
      },
      sm: {
        span: 24,
        offset: 0,
      },
      md: {
        span: 18,
        offset: 5,
      },
      lg: {
        span: 15,
        offset: 5,
      },
      xl: {
        span: 12,
        offset: 3,
      },
      xxl: {
        span: 12,
        offset: 3,
      },
    },
  }

  constructor(props: IUdFormProps) {
    super(props)
    this.state = {
      loading: false,
    }
  }

  componentDidMount() {
    if (_.isFunction(this.props.getForm)) {
      this.props.getForm(this.props.form)
    }
    this.setValues(this.props)
  }

  componentWillReceiveProps(nextProps: Readonly<IUdFormProps>) {
    if (!_.isEqual(this.props.values, nextProps.values)) {
      this.setValues(nextProps)
    }
  }

  render() {
    return (
      <Spin spinning={this.state.loading}>
        <Form
          className={classNames('ud-form', this.props.className)}
          layout={this.props.layout}
          onSubmit={this.handleSubmit}
        >
          <div className="ud-form-body">
            {this.props.items &&
              formUtils.buildFields(this.props.items, this.props.form, {
                wrapperCol: this.props.wrapperCol,
                labelCol: this.props.labelCol,
              })}
            {this.props.children}
          </div>
          {this.props.footer && (
            <div className="ud-form-footer">
              <Form.Item wrapperCol={this.props.tailFormItemLayout}>
                {_.isString(this.props.footer) ? (
                  <Button htmlType="submit" type="primary">
                    {this.props.footer}
                  </Button>
                ) : (
                  this.props.footer
                )}
              </Form.Item>
            </div>
          )}
        </Form>
      </Spin>
    )
  }

  private handleSubmit = (e: FormEvent) => {
    e.preventDefault()
    this.props.form.validateFieldsAndScroll((errors, values) => {
      if (errors) {
        if (this.props.onError) {
          this.props.onError(errors, values)
        } else {
          return
        }
      }
      let result = formUtils.handleValues(values, false)
      this.props.onSubmit(result)
    })
  }

  private setValues = props => {
    if (props.values) {
      if (_.isFunction(props.values)) {
        this.setState({ loading: true })
        props
          .values()
          .then(values => {
            // TODO 这里可能需要增加api来处理返回的values
            formUtils.setValues(this.props.form, props.items, values)
          })
          .finally(() => {
            this.setState({ loading: false })
          })
      } else {
        formUtils.setValues(this.props.form, props.items, props.values)
      }
    } else {
      formUtils.setValues(this.props.form, this.props.items, formUtils.getInitialValue(props.items))
    }
  }
}

export interface IUdFormProps extends FormComponentProps {
  /**
   * 表单项集合
   */
  items?: IUdFormItem[]
  /**
   * 设置表单的值。
   * 如果是设置初始值，请使用items
   */
  values?: { [key in string]: any } | (() => Promise<any>)
  /**
   * 提交事件，验证通过才会触发。
   */
  onSubmit?: (values: any) => void
  /**
   * 验证失败事件
   */
  onError?: (errors: any, values: any) => void
  /** 获取表单实例对象 */
  getForm?: (form: WrappedFormUtils) => void

  /**
   * 不管传没穿，都会有一个 ud-form
   */
  className?: Value

  /**
   * @default { xs: 24, sm: 24, md: 18, lg: 15, xl: 12, xxl: 12 }
   */
  wrapperCol?: ColProps
  /**
   * @default { xs: 24, sm: 24, md: 5, lg: 5, xl: 3, xxl: 3 }
   */
  labelCol?: ColProps
  /**
   * @default { xs: {span: 24, offset: 0}, sm: {span: 24, offset: 0}, md: {span: 18, offset: 5}, lg: {span: 15, offset: 5}, xl: {span: 12, offset: 3}, xxl: {span: 12, offset: 3}}
   */
  tailFormItemLayout?: ColProps

  /**
   * 表单底部，可放置 保存、重置等按钮。
   * 如果传入string，则表示 text为转入值的提交按钮。
   */
  footer?: string | ReactNode
  layout?: 'inline' | 'horizontal' | 'vertical'
}

export interface IUdFormState {
  loading: boolean
}

export { UdFormInner }

export default Form.create<IUdFormProps>()(UdFormInner)
